<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8" />
    <title>正弦波形成的可视化</title>
    <style>
        * {
            box-sizing: border-box;
        }

        body {
            --border: calc(1vmin / 4);
            --sine-ease: cubic-bezier(0.37, 0, 0.63, 1);
            --dur: 4s;
            --size: 40vmin;
            --gap: 4vmin;
            background-color: #fcecc9;
            margin: 0;
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
            transform: translate3d(0, 0, 0);
            overflow: hidden;
        }

        .grid {
            position: relative;
            display: grid;
            grid-template: 'c y' auto
                'x b' auto
                / auto auto;
            gap: var(--gap);
            animation: var(--dur) var(--sine-ease) calc(-0.5 * var(--dur)) infinite alternate x, var(--dur) var(--sine-ease) infinite alternate y, calc(var(--dur) * 2) linear infinite rot;
        }

        .circle {
            --color: rgb(123, 0, 126);
            --top: calc(var(--y) * 100%);
            --left: calc(var(--x) * 100%);
            grid-area: c;
            height: var(--size);
            width: var(--size);
            background-color: var(--color);
            border: var(--border) solid var(--color);
            border-radius: 50%;

            &:after {
                height: calc(var(--size) * 0.5);
                width: var(--border);
                background-color: #fcecc9;
                left: 50%;
                top: 0;
                transform-origin: 50% 100%;
                transform: rotate(calc(var(--rot) * 1turn));
            }
        }

        .x-bar {
            --color: rgb(126, 178, 221);
            --dim: var(--y);
            --top: 50%;
            --left: calc(var(--x) * 100%);
            grid-area: x;
            height: var(--border);
            width: var(--size);
            background-color: var(--color);

            &:after {
                left: calc(var(--x) * 100%);
                bottom: 0;
                height: var(--length);
                width: var(--width);
                transform: translate(-50%, 0);
            }
        }

        .x-wave {
            grid-area: x;
            top: 0;
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1 2' preserveAspectRatio='none'><path fill='rgb(126,178,221)' d='M 0 0 C 0 .37,1 .63,1 1 C 1 1.37,0 1.63,0 2 Z'></path></svg>");
            background-size: 100% 200%;
            background-position: top calc(var(--size) * 0.5 + (var(--rot) * 2 * var(--size))) center;
            background-repeat: repeat-y;
            border-radius: 0 0 calc(var(--size) * 0.125) calc(var(--size) * 0.125);
        }

        .y-bar {
            --color: rgb(249, 57, 67);
            --dim: var(--x);
            --top: calc(var(--y) * 100%);
            --left: 50%;
            grid-area: y;
            width: var(--border);
            height: var(--size);
            background-color: var(--color);

            &:after {
                top: calc(var(--y) * 100%);
                right: 50%;
                width: var(--length);
                height: var(--width);
                transform: translate(0, -50%);
            }
        }

        .y-wave {
            grid-area: y;
            left: 0;
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 1' preserveAspectRatio='none'><path fill='rgb(249,57,67)' d='M 0 0 C .37 0,.63 1,1 1 C 1.37 1,1.63 0,2 0 Z'></path></svg>");
            background-size: 200% 100%;
            background-position: center left calc(var(--rot) * 2 * var(--size));
            background-repeat: repeat-x;
            border-radius: 0 calc(var(--size) * 0.125) calc(var(--size) * 0.125) 0;
        }

        .xy-wave {
            grid-area: b;
            left: 0;
            background-blend-mode: color-burn;
            background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 1' preserveAspectRatio='none'><path fill='rgb(249,57,67)' d='M 0 1 C .37 1,.63 0,1 0 C 1.37 0,1.63 1,2 1 Z'></path></svg>"), url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 2 1' preserveAspectRatio='none'><path fill='rgb(126,178,221)' d='M 0 1 C .37 1,.63 0,1 0 C 1.37 0,1.63 1,2 1 Z'></path></svg>");
            background-size: 200% 100%;
            background-repeat: repeat-x;
            background-position: center left calc(var(--rot) * 2 * var(--size)), center left calc(var(--size) * 0.5 + (var(--rot) * 2 * var(--size)));
            border-radius: calc(var(--size) * 0.125);
        }

        .x-wave,
        .y-wave,
        .xy-wave {
            position: relative;
            width: var(--size);
            height: var(--size);
        }

        .circle,
        .x-bar,
        .y-bar {
            position: relative;

            &:before {
                content: '';
                position: absolute;
                top: var(--top);
                left: var(--left);
                height: calc(var(--size) / 32);
                width: calc(var(--size) / 32);
                background-color: #fcecc9;
                border: var(--border) solid var(--color);
                border-radius: 50%;
                transform: translate(-50%, -50%);
                z-index: 1;
            }

            &:after {
                content: '';
                position: absolute;
            }
        }

        .x-bar,
        .y-bar {
            --length: calc(var(--gap) + ((1 - var(--dim)) * var(--size)));
            --width: var(--border);

            &:after {
                background-color: var(--color);
            }
        }

        @keyframes x {
            from {
                --x: 0;
            }

            to {
                --x: 1;
            }
        }

        @keyframes y {
            from {
                --y: 0;
            }

            to {
                --y: 1;
            }
        }

        @keyframes rot {
            from {
                --rot: 0;
            }

            to {
                --rot: 1;
            }
        }

        @property --x {
            syntax: '<number>';
            inherits: true;
            initial-value: 0.5;
        }

        @property --y {
            syntax: '<number>';
            inherits: true;
            initial-value: 0;
        }

        @property --rot {
            syntax: '<number>';
            inherits: true;
            initial-value: 0;
        }
    </style>
</head>

<body>
    <div class="grid">
        <div class="circle"></div>
        <div class="x-bar"></div>
        <div class="x-wave"></div>
        <div class="y-bar"></div>
        <div class="y-wave"></div>
        <div class="xy-wave"></div>
    </div>
</body>

</html>